package conf

import (
	"flag"
	"fmt"
	"os"

	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

// NetConfig .
type NetConfig struct {
	Server   Server    `yaml:"server"`
	Registry Registry  `yaml:"registry"`
	Dal      DalItem   `json:"dal" yaml:"dal"`
	Default  Default   `yaml:"registry"`
	Redis    RedisItem `json:"redis" yaml:"redis"`
}
type RedisItem struct {
	Addr     string       `json:"addr"`
	Password string       `json:"password"`
	Db       int          `json:"db"`
	Sentinel SentinelItem `json:"sentinel" yaml:"sentinel"`
}

type SentinelItem struct {
	MasterName       string   `json:"master_name" yaml:"master_name"`
	SentinelAddrs    []string `json:"sentinel_addrs" yaml:"sentinel_addrs"`
	SentinelPassword string   `json:"sentinel_password" yaml:"sentinel_password"`
}

type ResourceItem struct {
	PortItemMaxNum int `json:"port_item_max_num" yaml:"port_item_max_num"`
}

type AccessNetItem struct {
	GatewayMaxNum            int64                 `json:"gateway_max_num" yaml:"gateway_max_num"`
	GatewayMaxReconnectedSec int64                 `json:"gateway_max_reconnected_sec" yaml:"gateway_max_reconnected_sec"`
	GatewayAesSalt           string                `json:"gateway_aes_salt" yaml:"gateway_aes_salt"`
	GatewaySignSalt          string                `json:"gateway_sign_salt" yaml:"gateway_sign_salt"`
	GatewayInstallCmd        GatewayInstallCmdItem `json:"gateway_install_cmd" yaml:"gateway_install_cmd"`
}

type PkiItem struct {
	ProxyTarget      string `json:"proxy_target" yaml:"proxy_target"`
	JwtAud           string `json:"jwt_aud" yaml:"jwt_aud"`
	JwtIss           string `json:"jwt_iss" yaml:"jwt_iss"`
	JwtKid           string `json:"jwt_kid" yaml:"jwt_kid"`
	JwtPayLoadSha    string `json:"jwt_pay_load_sha" yaml:"jwt_pay_load_sha"`
	JwtEncryptedKey  string `json:"jwt_encrypted_key" yaml:"jwt_encrypted_key"`
	JwtDecryptPasswd string `json:"jwt_decrypt_passwd" yaml:"jwt_decrypt_passwd"`
}

type EdgesDeployTokenSettingItem struct {
	SignSalt      string            `json:"sign_salt" yaml:"sign_salt"`
	ApiServer     string            `json:"api_server" yaml:"api_server"`
	ExpiredSecond int64             `json:"expired_second" yaml:"expired_second"`
	ShellTemplate ShellTemplateItem `json:"shell_template" yaml:"shell_template"`
}

type DeploymentsTokenSettingItem struct {
	SignSalt      string            `json:"sign_salt" yaml:"sign_salt"`
	ExpiredSecond int64             `json:"expired_second" yaml:"expired_second"`
	ShellTemplate ShellTemplateItem `json:"shell_template" yaml:"shell_template"`
}

type ShellTemplateItem struct {
	Single         string `json:"single" yaml:"single"`
	Bulk           string `json:"bulk" yaml:"bulk"`
	HeadlessClient string `json:"headless_client" yaml:"headless_client"`
}

type GatewayInstallCmdItem struct {
	Linux   string `json:"linux" yaml:"linux"`
	Aws     string `json:"aws" yaml:"aws"`
	Ali     string `json:"ali" yaml:"ali"`
	Tencent string `json:"tencent" yaml:"tencent"`
}

// DalItem .
type DalItem struct {
	DataSource string            `json:"data_source" yaml:"data_source"`
	DbConnPool DbConnPoolSetting `json:"db_conn_pool" yaml:"db_conn_pool"`
}

// DbConnPoolSetting .
type DbConnPoolSetting struct {
	SetMaxIdleConns    int
	SetMaxOpenConns    int
	SetConnMaxLifetime int
}

// Server .
type Server struct {
	Name      string        `yaml:"name"`
	Service   Service       `yaml:"service"`
	RateLimit RateLimitItem `yaml:"rate_limit"`
}
type RateLimitItem struct {
	MaxConn int `yaml:"max_conn"`
	MaxQps  int `yaml:"max_qps"`
}

// Service .
type Service struct {
	Name    string `yaml:"name"`
	Address string `yaml:"address"`
	Port    int    `yaml:"port"`
}

// Registry .
type Registry struct {
	Type    string `yaml:"type"`
	Address string `yaml:"address"`
	Token   string `json:"token" yaml:"token"`
}

// Default .
type Default struct {
	DashDomain     string `yaml:"dash_domain"`
	DownloadPrefix string `yaml:"download_prefix"`
}

var Config = NetConfig{}

// Init .
func Init() {
	env := os.Getenv("ENV")
	cFlag := ""
	confFile := ""
	flag.StringVar(&cFlag, "c", "conf/local.yaml", "conf path")
	flag.Parse()

	if cFlag != "" {
		confFile = cFlag
	} else if env != "" {
		confFile = fmt.Sprintf("conf/%s.yaml", env)
	} else {
		panic(any("config file not found!"))
	}
	viper.SetConfigFile(confFile)
	if err := viper.ReadInConfig(); err != nil { // 处理读取配置文件的错误
		panic(any(fmt.Errorf("fatal error config file: %w", err)))
	}
	if err := viper.Unmarshal(&Config); err != nil {
		fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
		return
	}
	fmt.Printf("Config:%#v\n", Config)
	// 第二：实时监控配置文件的变化
	viper.WatchConfig()
	viper.OnConfigChange(
		func(e fsnotify.Event) {
			// 配置文件发生变更之后会调用的回调函数
			fmt.Println("Config file changed:", e.Name)
			if err := viper.Unmarshal(&Config); err != nil {
				fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
			}
		},
	)
}
